//NEED TO REMEMBER THAT ON MATRIX INDEX 1
//NEED TO CHANGE CODE TO MOVE DOWNWARDS AND NOT SIDEWARDS


import java.util.*;
public class Solution {
    
    static int matrixNumber=0;
    static List<List<Integer>> matrix = new ArrayList<>();
    static List<List <Integer>> nextMatrix;
    
    public static void main (String [] args)
    {
        
        List <List<List<Integer>>> testMatrix = new ArrayList<>(); 
        //TEST CASES
        //We have to ensure that the test case is a 3d array as oppose to a 2d array to contain all the matrixes
        
        Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{7,8},{9,10},{11,12}},  { {13,14}, {15,16}} 
                                               };

        for (Integer [][] item: test)
        {
            //THIS WAS CRITICAL PIECE OF CODE HERE...
            //OTHERWISE THERE WOULD BE THE SAME OBJECT REFERENCE EACH TIME!
            matrix = new ArrayList<>();
            
            //At this point we have the entire contents that would represent the List<List<Integer> single matrix
            //since we know that {1,2,3} would be a List<Integer> and {4,5,6} would be a list <Integer>
        
            for (Integer [] row: item)
            {
                matrix.add(Arrays.asList(row));    //similar to transposing matrix challenge
            }
            testMatrix.add(matrix);
        }
        
        matrixNumber=0;
        //method call
        matrixMultiplication(testMatrix);
    }
    
    
    public static List<List<Integer>> matrixMultiplication(List<List<List<Integer>>> matrices) 
    {
        List<List<Integer>> finalMatrix = new ArrayList<List<Integer>>();

        List<Integer> temp = new ArrayList<Integer>();
        int rowsNextMatrix=0;
        int size=0;
        int matricesSize=matrices.size();
        int numElementsInList=0;
        int counter=0;
        int i;
        int currentInteger;
        
        boolean hasStartMatrix=true;
        boolean hasPerformedValidation=false;
        int numElementsInRow=0;
        boolean hasProcessed=false;

        
        int numMatrixes=0;

        //I am using this size based on principle that
        //number columns Matrix A needs to be equal 
        //number rows Matrix B
        //This is easiest way to ascertain a suitable dimension
        //of Matrix B
        //really this would need to be in a try and catch statement should there only be one matrix!

	//we know the first row dimension, this must match the number columns Matrix B
    //So both take same dimensions

    //lets say if there is also matrix C
    //we would apply the principle again both dimensions are taken from matrix C column size.
    //Hence it is best not to declare size at moment

    int [][]matrixValue;

    //int [][]matrixValue = new int[matrices.get(1).size()][matrices.get(1).size()];

    

        
        //The following structure will ensure that
        //each each matrix can be obtained from the matrices
        //We have to remember that inner Lists can still be accessed via their index locations. This can be obtained via .get
        //We know that similar to other transposing matrix challenge, we can obtain the size (matrices) which will output the number of elements..
        //We know in this case this deals with List<List<Integer>>
        //We can now formulate a do while loop which would process the List<List<Integer>> within matrices until it reaches the size of matrices.

        //This will present all matrix in true form in order to visualise and assist with coding 
        System.out.println("***ALL MATRIX*******");
        do
        {
            matrix=matrices.get(numMatrixes);
            
            System.out.println("\n\nMatrix" +"("+numMatrixes+"):");

            for (List<Integer> row: matrix)
            {
                System.out.println(row);
            }
            numMatrixes++;
            System.out.println("\n");
            }while(numMatrixes<matrices.size());

            numMatrixes=0;

       //This do while loop is main code and can execute up to (matrices.size()-1)
       do
        {
            hasProcessed=false;
            matrix=matrices.get(counter);
            System.out.println("\n\n------Matrix" +"("+counter+"):");

        for (List<Integer> ee: matrix)
        {
            //I can no longer use this notation since it will not be compatible with rest of my code
            
            for (int k=0; k<ee.size(); k++)
            {
                currentInteger = ee.get(k);
                //I am now choosing to look ahead at the next matrix as soon as a number appears on the screen.
                //The only exception of course is the final matrix since it would have been processed by penultimate matrix.

                if(counter!=matricesSize-1)
                {
                
                //In this matrix we know that numbers are retrieved left to right.
                //I am going to attempt completing the multiplication in a similar manner to a human.
                /*
                [1, 2, 3] 
                [4, 5, 6]

                [7,    8] 
                [9,   10]
                [11, 12]
                */
          
            
            //we would perform this to obtain the next matrix
            //matrix=matrices.get(counter+1);
            
            //we would perform this to obtain the next matrix
            //I had to scrap this since for some reason, it was giving information for incorrect matrix.
            //I do not think issue was related to object referencing..
            //But I am going to stay away for now
            nextMatrix=matrices.get(counter+1);

            if (!hasProcessed)
            {
            
            //OPTION 1 - largely non index based
            for (List<Integer> rows: nextMatrix)
            {
                for (int s: rows)
                {

                }
            }

            //But I also have this option to perform a similar operation as above but at a more granular level

            //we have created an outer if loop because it will otherwise execute multiple times. We are only seeking one occurrence for next matrix
            
            
            
            System.out.println("number rows in matrix "+ "("+(counter+1)+"): -  " + nextMatrix.size());
            System.out.println("number cols in matrix "+ "("+(counter+1)+"): -  " + nextMatrix.get(0).size());  

             //OPTION 2 - index based
             
             List<Integer> rowInfo = new ArrayList<>();
             int pos=0;
             int posPrevMatrixRowLevel=0;
             
             
             //this will go through each column
                    for (int z=0; z<nextMatrix.get(0).size(); z++)
                    {
                        //for each column we stil need to get the entire row
                    for (int y=0; y<nextMatrix.size();y++)
                    {
                        System.out.println("*****************VALUE Y: " + y);
             
            //this is getting the rows from the nextmatrix 
            for (int m=0; m<nextMatrix.size(); m++)
            {   
                //for each row we need to get the size so that all integers can be collated from the row
                for (int j=0;j<nextMatrix.get(m).size();j++)
                {
                    //int [] row  = new int[]Arrays.asList(nextMatrix.get(m));
                    //int [] row = {1,2,3};
                    
                    
                    rowInfo=new ArrayList<>(nextMatrix.get(m));
                    System.out.println("size: " + rowInfo.size());
                    
                    
                    //but we know that we are only interested in the first item from each row
                    //since we are processing the column
                    
                    //AT THIS MOMENT, WE HAVE TWO FOR LOOPS WHICH IS GOING THROUGH ROWS
                    //IN NEXT MATRIX AND ALSO CREATED THE ROW IN A LIST
                    
                    //------
                        
                        //once we go through the rows, we need to get the actual row
                        
                    
                    //for (int p=0; p<rowInfo.size(); p++)
                    //{
                        System.out.println("element: " + rowInfo.get(y));
                        posPrevMatrixRowLevel=0;
                        
                        //in here need to go through the row in previous matrix
                        //this is the row level
                        
                         for (int g=0; g<ee.size(); g++)
                        {
                            System.out.println("INFO prev: " +ee.get(g+posPrevMatrixRowLevel));
                            
                        }
                        posPrevMatrixRowLevel++;
                        
                        
                        
                        System.out.println("vak k: " + ee.get(k+pos));
                        
                        pos++;
                        break;
                    //}
                    }
                }
                    pos=0;
                }                
            }

            hasProcessed=true;
            
            }
            
            
            
            




                }


                if (matrixNumber<counter && hasStartMatrix)
                {
                    System.out.println("This is first integer in next matrix: " + k);
                    hasStartMatrix=false;  
                    hasProcessed=false; 
                }

                numElementsInList++;
                numElementsInRow++;
                System.out.println("Integer: " + currentInteger);
            }
            

            //Using this technique will also ensure that I can check if the matrix is valid dimension and terminate the application
            //WE KNOW THAT NUMBER columns in Matrix A should match rows Matrix B
	    //NOTE for simplicity, I have assumed columms in Matrix A are uniform across its rows.
	    //We know if it had a jagged array, it would be a mismatch against the number rows in Matrix B	
           //Once I have finished the entire challenge, I can potentially extend my validation at this level
           //Since in this challenge there is every possibility of human error populating the matrix!

            if(counter!=(matricesSize-1) && !hasPerformedValidation)
            {
                for (List<Integer> rows: matrices.get((counter+1)))
                {
                    rowsNextMatrix++;
                }

                    if (numElementsInRow!=rowsNextMatrix)
                    {
            System.out.println("columns in Matrix A" + "("+numElementsInRow+")"+ "should match rows Matrix B " +  "("+rowsNextMatrix+")");
                        System.exit(0);
                    }
                    else
                    {
                        System.out.println("columns in Matrix A " + "("+numElementsInRow+")" + " rows Matrix B: " + "("+rowsNextMatrix+")");
                    }
                    hasPerformedValidation=true;
            }

            numElementsInRow=0;

            //break;
        }
        matrixNumber=counter;

        //since we alternate between matrixes
        counter=counter+2;

        hasStartMatrix=true;
        hasPerformedValidation=false;
        rowsNextMatrix=0;
        //hasProcessed=false;

        numMatrixes++;

        }while (counter<matricesSize);

        System.out.println("num elements: " + numElementsInList);

        return finalMatrix;
    }
}
